{{>licenseInfo}}
/* tslint:disable:no-unused-variable member-ordering */

{{#useAxiosHttpModule}}
import { Injectable, Optional } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
{{/useAxiosHttpModule}}
{{^useAxiosHttpModule}}
import { HttpService, Injectable, Optional } from '@nestjs/common';
{{/useAxiosHttpModule}}
import { AxiosResponse } from 'axios';
import { Observable, from, of, switchMap } from 'rxjs';
{{#imports}}
import { {{classname}} } from '../{{filename}}';
{{/imports}}
import { Configuration } from '../configuration';
import { COLLECTION_FORMATS } from '../variables';
{{#withInterfaces}}
import { {{classname}}Interface } from './{{classFilename}}Interface';
{{/withInterfaces}}

{{#operations}}
{{#useSingleRequestParameter}}
{{#operation}}
{{#allParams.0}}
/**
 * Request parameters for {{nickname}} operation in {{classname}}.
 * @export
 * @interface {{classname}}{{operationIdCamelCase}}Request
 */
export interface {{classname}}{{operationIdCamelCase}}Request {
    {{#allParams}}
    /**
     * {{description}}
     * @type {{=<% %>=}}{<%&dataType%>}<%={{ }}=%>
     * @memberof {{classname}}{{operationIdCamelCase}}
     */
    readonly {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}
    {{^-last}}

    {{/-last}}
    {{/allParams}}
}

{{/allParams.0}}
{{/operation}}
{{/useSingleRequestParameter}}

{{#description}}
/**
 * {{&description}}
 */
{{/description}}
@Injectable()
{{#withInterfaces}}
export class {{classname}} implements {{classname}}Interface {
{{/withInterfaces}}
{{^withInterfaces}}
export class {{classname}} {
{{/withInterfaces}}

    protected basePath = '{{{basePath}}}';
    public defaultHeaders: Record<string,string> = {};
    public configuration = new Configuration();

    constructor(protected httpClient: HttpService, @Optional() configuration: Configuration) {
        this.configuration = configuration || this.configuration;
        this.basePath = configuration?.basePath || this.basePath;
    }

    /**
     * @param consumes string[] mime-types
     * @return true: consumes contains 'multipart/form-data', false: otherwise
     */
    private canConsumeForm(consumes: string[]): boolean {
        const form = 'multipart/form-data';
        return consumes.includes(form);
    }

{{#operation}}
    /**
     * {{summary}}
     * {{notes}}
     {{#useSingleRequestParameter}}
     {{#allParams.0}}
     * @param {{=<% %>=}}{<%& classname %><%& operationIdCamelCase %>Request}<%={{ }}=%> requestParameters Request parameters.
     {{/allParams.0}}
     {{/useSingleRequestParameter}}
     {{^useSingleRequestParameter}}
     {{#allParams}}* @param {{paramName}} {{description}}
     {{/allParams}}* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
     * @param reportProgress flag to report request and response progress.
     {{/useSingleRequestParameter}}
     */
    {{#useSingleRequestParameter}}
    public {{nickname}}({{#allParams.0}}requestParameters: {{classname}}{{operationIdCamelCase}}Request, {{/allParams.0}}): Observable<AxiosResponse<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>>;
    public {{nickname}}({{#allParams.0}}requestParameters: {{classname}}{{operationIdCamelCase}}Request, {{/allParams.0}}): Observable<any> {
    {{/useSingleRequestParameter}}
    {{^useSingleRequestParameter}}
    public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable<AxiosResponse<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>>;
    public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable<any> {
    {{/useSingleRequestParameter}}
{{#allParams.0}}
{{#useSingleRequestParameter}}
        const {
        {{#allParams}}
            {{paramName}},
        {{/allParams}}
        } = requestParameters;

{{/useSingleRequestParameter}}
{{/allParams.0}}
{{#allParams}}
{{#required}}
        {{#isConstEnumParam}}
        let {{paramName}} = {{{dataType}}};
        {{/isConstEnumParam}}
        {{^isConstEnumParam}}
        if ({{paramName}} === null || {{paramName}} === undefined) {
            throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
        }

        {{/isConstEnumParam}}
{{/required}}
{{/allParams}}
{{#hasQueryParams}}
        let queryParameters = new URLSearchParams();
{{#queryParams}}
        {{#isArray}}
        if ({{paramName}}) {
        {{#isCollectionFormatMulti}}
            {{paramName}}.forEach((element) => {
                queryParameters.append('{{baseName}}', <any>element);
            })
        {{/isCollectionFormatMulti}}
        {{^isCollectionFormatMulti}}
            queryParameters['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']);
        {{/isCollectionFormatMulti}}
        }
        {{/isArray}}
        {{^isArray}}
        if ({{paramName}} !== undefined && {{paramName}} !== null) {
        {{#isDateTime}}
            queryParameters.append('{{baseName}}', (<any>{{paramName}}).toISOString());
        {{/isDateTime}}
        {{^isDateTime}}
            queryParameters.append('{{baseName}}', <any>{{paramName}});
        {{/isDateTime}}
        }
        {{/isArray}}
{{/queryParams}}

{{/hasQueryParams}}
        let headers = {...this.defaultHeaders};
{{#headerParams}}
        {{#isArray}}
        if ({{paramName}}) {
            headers['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']);
        }
        {{/isArray}}
        {{^isArray}}
        if ({{paramName}} !== undefined && {{paramName}} !== null) {
            headers['{{baseName}}'] = String({{paramName}});
        }
        {{/isArray}}
{{/headerParams}}

        let accessTokenObservable: Observable<any> = of(null);

{{#authMethods}}
        // authentication ({{name}}) required
{{#isApiKey}}
{{#isKeyInHeader}}
        if (this.configuration.apiKeys?.["{{keyParamName}}"]) {
            headers['{{keyParamName}}'] = this.configuration.apiKeys["{{keyParamName}}"];
        }

{{/isKeyInHeader}}
{{#isKeyInQuery}}
        {{^hasQueryParams}}
        let queryParameters = new URLSearchParams();
        {{/hasQueryParams}}
        if (this.configuration.apiKeys?.["{{keyParamName}}"]) {
            queryParameters.append('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]);
        }

{{/isKeyInQuery}}
{{/isApiKey}}
{{#isBasicBasic}}
        if (this.configuration.username || this.configuration.password) {
            headers['Authorization'] = 'Basic ' + btoa(this.configuration.username + ':' + this.configuration.password);
        }

{{/isBasicBasic}}
{{#isBasicBearer}}
        if (typeof this.configuration.accessToken === 'function') {
            accessTokenObservable = from(Promise.resolve(this.configuration.accessToken()));
        } else if (this.configuration.accessToken) {
            accessTokenObservable = from(Promise.resolve(this.configuration.accessToken));
        }
{{/isBasicBearer}}
{{#isOAuth}}
        if (this.configuration.accessToken) {
            accessTokenObservable = typeof this.configuration.accessToken === 'function'
                ? from(Promise.resolve(this.configuration.accessToken()))
                : from(Promise.resolve(this.configuration.accessToken))
        }

{{/isOAuth}}
{{/authMethods}}
        // to determine the Accept header
        let httpHeaderAccepts: string[] = [
            {{#produces}}
            '{{{mediaType}}}'{{^-last}},{{/-last}}
            {{/produces}}
        ];
        const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
        if (httpHeaderAcceptSelected != undefined) {
            headers['Accept'] = httpHeaderAcceptSelected;
        }

        // to determine the Content-Type header
        const consumes: string[] = [
            {{#consumes}}
            '{{{mediaType}}}'{{^-last}},{{/-last}}
            {{/consumes}}
        ];
{{#bodyParam}}
        const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
        if (httpContentTypeSelected != undefined) {
            headers['Content-Type'] = httpContentTypeSelected;
        }
{{/bodyParam}}
{{#hasFormParams}}

        const canConsumeForm = this.canConsumeForm(consumes);

        let formParams: { append(param: string, value: any): void; };
        let useForm = false;
        let convertFormParamsToString = false;
{{#formParams}}
{{#isFile}}

        // use FormData to transmit files using content-type "multipart/form-data"
        // see https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data
        useForm = canConsumeForm;
{{/isFile}}
{{/formParams}}
        if (useForm) {
            formParams = new FormData();
        } else {
            // formParams = new HttpParams({encoder: new CustomHttpUrlEncodingCodec()});
        }
{{#formParams}}

        {{#isArray}}
        if ({{paramName}}) {
        {{#isCollectionFormatMulti}}
            {{paramName}}.forEach((element) => {
                formParams!.append('{{baseName}}', <any>element);
            })
        {{/isCollectionFormatMulti}}
        {{^isCollectionFormatMulti}}
            formParams!.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']));
        {{/isCollectionFormatMulti}}
        }
        {{/isArray}}
        {{^isArray}}
        if ({{paramName}} !== undefined) {
            formParams!.append('{{baseName}}', <any>{{paramName}});
        }
        {{/isArray}}
{{/formParams}}

{{/hasFormParams}}
        return accessTokenObservable.pipe(
            switchMap((accessToken) => {
                if (accessToken) {
                    headers['Authorization'] = `Bearer ${accessToken}`;
                }

                return this.httpClient.{{httpMethod}}{{^isResponseFile}}<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>{{/isResponseFile}}(`${this.basePath}{{{path}}}`,{{#isBodyAllowed}}
                    {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}}
                    {
        {{#hasQueryParams}}
                        params: queryParameters,
        {{/hasQueryParams}}
        {{#isResponseFile}}
                        responseType: "blob",
        {{/isResponseFile}}
                        withCredentials: this.configuration.withCredentials,
                        headers: headers
                    }
                );
            })
        );
    }
{{/operation}}
}
{{/operations}}
